package cn.afterturn.easypoi.excel.html.helper;

import cn.afterturn.easypoi.excel.html.entity.style.CellStyleBorderEntity;
import cn.afterturn.easypoi.util.PoiCellUtil;
import cn.afterturn.easypoi.util.PoiMergeCellUtil;
import com.sun.corba.se.spi.orbutil.threadpool.Work;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 合并单元格帮助类
 *
 * @author JueYue
 * 2015年5月9日 下午2:13:35
 */
public class MergedRegionHelper {

    private Map<String, Integer[]> mergedCache = new HashMap<String, Integer[]>();

    private Set<String> notNeedCache = new HashSet<String>();

    public MergedRegionHelper(Sheet sheet) {
        getAllMergedRegion(sheet);
    }

    public void getAllMergedRegion(Sheet sheet) {
        int nums = sheet.getNumMergedRegions();
        mergedCache.clear();
        notNeedCache.clear();
        for (int i = 0; i < nums; i++) {
            handlerMergedString(sheet.getMergedRegion(i), sheet.getMergedRegion(i).formatAsString());
        }
    }

    /**
     * 根据合并输出内容,处理合并单元格事情
     *
     * @param formatAsString
     */
    private void handlerMergedString(CellRangeAddress cellRangeAddress, String formatAsString) {
        String[] strArr = formatAsString.split(":");
        if (strArr.length == 2) {
            int startCol = strArr[0].charAt(0) - 65;
            if (strArr[0].charAt(1) >= 65) {
                startCol = (startCol + 1) * 26 + (strArr[0].charAt(1) - 65);
            }
            int startRol = Integer.valueOf(strArr[0].substring(strArr[0].charAt(1) >= 65 ? 2 : 1));
            int endCol = strArr[1].charAt(0) - 65;
            if (strArr[1].charAt(1) >= 65) {
                endCol = (endCol + 1) * 26 + (strArr[1].charAt(1) - 65);
            }
            int endRol = Integer.valueOf(strArr[1].substring(strArr[1].charAt(1) >= 65 ? 2 : 1));
            mergedCache.put(startRol + "_" + startCol,
                    new Integer[]{endRol - startRol + 1, endCol - startCol + 1});
            for (int i = startRol; i <= endRol; i++) {
                for (int j = startCol; j <= endCol; j++) {
                    notNeedCache.add(i + "_" + j);
                }
            }
            notNeedCache.remove(startRol + "_" + startCol);
        }

    }

    /**
     * 是不是需要创建这个TD
     *
     * @param row
     * @param col
     * @return
     */
    public boolean isNeedCreate(int row, int col) {
        return !notNeedCache.contains(row + "_" + col);
    }

    /**
     * 是不是合并区域
     *
     * @param row
     * @param col
     * @return
     */
    public boolean isMergedRegion(int row, int col) {
        return mergedCache.containsKey(row + "_" + col);
    }

    /**
     * 获取合并区域
     *
     * @param row
     * @param col
     * @return
     */
    public Integer[] getRowAndColSpan(int row, int col) {
        return mergedCache.get(row + "_" + col);
    }

    /**
     * 插入之后还原之前的合并单元格
     *
     * @param rowIndex
     * @param size
     */
    public void shiftRows(Sheet sheet, int rowIndex, int size) {
        Set<String> keys = new HashSet<String>();
        keys.addAll(mergedCache.keySet());
        for (String key : keys) {
            String[] temp = key.split("_");
            if (Integer.parseInt(temp[0]) >= rowIndex) {
                Integer[] data = mergedCache.get(key);
                String newKey = (Integer.parseInt(temp[0]) + size) + "_" + temp[1];
                if (!mergedCache.containsKey(newKey)) {
                    mergedCache.put(newKey, mergedCache.get(key));
                    try {
                        // 还原合并单元格
                        if (!PoiCellUtil.isMergedRegion(sheet, Integer.parseInt(temp[0]) + size - 1, Integer.parseInt(temp[1]))) {
                            PoiMergeCellUtil.addMergedRegion(sheet,
                                    Integer.parseInt(temp[0]) + size - 1, Integer.parseInt(temp[0]) + data[0] + size - 2,
                                    Integer.parseInt(temp[1]), Integer.parseInt(temp[1]) + data[1] - 1
                            );
                        }
                    } catch (Exception e) {
                    }
                }
            }
        }
    }

    public void shiftRowsNew(Sheet sheet, int rowIndex, int size) {
        Row row = sheet.getRow(rowIndex);
        if (row == null) {
            return ;
        }
        Map<String,String> cache = new HashMap<>();
        //循环处理每个单元格
        for (int i=row.getFirstCellNum();i<row.getLastCellNum();i++) {
            Cell cell = row.getCell(i);
            CellStyle style  = row.getCell(i).getCellStyle();
            Result mergedRegion = isMergedRegion(sheet, rowIndex, i);
            if (mergedRegion.merged) {
                if(mergedRegion.endRow - mergedRegion.startRow > 0) {
                    int startCol = mergedRegion.startCol-1;
                    int endCol = mergedRegion.endCol-1;
                    String flag = mergedRegion.startRow - 1+"_"+startCol+"_"+endCol;
                    if (cache.containsKey(flag)) {
                        continue;
                    }
                    PoiMergeCellUtil.removeMergedRegion(sheet, mergedRegion.startRow - 1, startCol);
                    PoiMergeCellUtil.addMergedRegion(sheet,
                            mergedRegion.startRow - 1, mergedRegion.endRow + size-1 ,
                            startCol, endCol
                    );
                    //标记已处理
                    cache.put(flag,"true");
                    CellRangeAddress range = mergedRegion.range;
                    range.setFirstColumn(startCol);
                    range.setFirstRow(mergedRegion.startRow - 1);
                    range.setLastColumn(endCol);
                    range.setLastRow(mergedRegion.endRow + size-1);
                    setBorderStyle(style.getBorderTop(),mergedRegion.range,row.getSheet());
                }
            }
        }
    }

    public void setBorderStyle(BorderStyle borderStyle, CellRangeAddress region, Sheet sheet){
        RegionUtil.setBorderBottom(borderStyle, region, sheet); //下边框
        RegionUtil.setBorderLeft(borderStyle, region, sheet);     //左边框
        RegionUtil.setBorderRight(borderStyle, region, sheet);    //右边框
        RegionUtil.setBorderTop(borderStyle, region, sheet);      //上边框
    }

    public Result isMergedRegion(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    return new Result(true, firstRow + 1, lastRow + 1, firstColumn + 1, lastColumn + 1,range);
                }
            }
        }
        return new Result(false, 0, 0, 0, 0,null);
    }

    public static class Result {
        public boolean merged;
        public int startRow;
        public int endRow;
        public int startCol;
        public int endCol;
        public CellRangeAddress range;

        public Result(boolean merged, int startRow, int endRow
                , int startCol, int endCol,CellRangeAddress range) {
            this.merged = merged;
            this.startRow = startRow;
            this.endRow = endRow;
            this.startCol = startCol;
            this.endCol = endCol;
            this.range = range;
        }
    }

}
